Quickie Tutorial - using breakpoints to find graphics data (example 1) by Labmaster, 24/03/06 This is a really brief tutorial on how to use VBA-SDL-H to find graphics data in a Gameboy Advance game. Assumes basic knowledge of VBA-SDL-H (read the documentation :p), and some techy stuff. Any questions, ask someone at ROMHacking.net Target: The Legend of Zelda, The Minish Cap (title screen logo). First step is to find where the graphics data is in VRAM, and the first place we look is on the various backgrounds. Open the Map Viewer in normal VBA, and see if it's one of the Backgrounds. In this case, it's not, so it must be a sprite. To confirm this, open the OAM viewer and scroll across until you find the parts of the logo. Now - a quick background on GBA sprites. The actual graphics are stored at 0x06010000, (OAM data, which controls position, scaling etc..., is at 0x07000000), so open the tile viewer and select the 0x601000 char base. The screen looks blank, so try it with various palette's until something comes up. You should see the tiles that make up the logo (note the three different palettes used for the red logo, the green 'Minish Cap' text, and the sword. So, now we need to figure out where in the ROM this data has come from. To do this, we'll use VBA-SDL-H's write breakpoints. Click on one of the tiles that make up the logo (for this example, we'll use the top-right of the 'Z'). The Tile Viewer will give you the address for this tile - 06013020. Open the ROM in VBA-SDL-H, let the intro run until just before the logo appears (we can tell that the logo hasn't been written into VRAM into this stage by observing the tile viewer in normal VBA with 'Automatic update' button checked, as the game runs through the intro). Enter the debugging console, and place a write breakpoint on the tile by typing in: bpw 06013020 20 This puts a write breakpoint for the 20 bytes starting at 06013020, it doesn't really matter how big this is for this breakpoint (you could just set it to 1). Continue the game, and it should break thus: Breakpoint (on write) address 06013020 old:00000000 new:00000000 Breakpoint (on write) address 06013024 old:00000000 new:00000000 Breakpoint (on write) address 06013028 old:00000000 new:00000000 Breakpoint (on write) address 0601302C old:00000000 new:cccc0000 Breakpoint (on write) address 06013030 old:00000000 new:eeccc000 R00=84000580 R04=00000004 R08=00000000 R12=03000090 R01=84000000 R05=00000030 R09=00000000 R13=03007ecc R02=040000d4 R06=03001000 R10=00000000 R14=080addcf R03=020244c4 R07=00000000 R11=00000000 R15=080adf40 CPSR=8000003f (N.....T Mode: 1f) 080adf3e 6890 ldr r0, [r2, #0x8] How do we know that this is the right break? If you open the memory viewer in VBA and see what 06013020 is whilst on the menu, you'll know that these are the correct values. So now we need to see what opcode triggered this breakpoint. In VBA's diassembly viewer, go to 080adf3e and scroll up a bit. The instruction that triggered the breakpoint is the one immediately before 080adf3e, i.e.: 080adf3c 6090 str r0, [r2, #0x8] This writes the value in r0 to the address in r02 + 0x8. Now this is where it's handy to know your GBA IO registers. The address in r02, 0x040000d4, is one of those that control DMA transfers (if you don't know what DMA is, google it). 0x040000D4 + 0x8 is 040000DC, and we're writing a word to it - this actually corresponds to both the word count register and control register for DMA channel 3. (How do I know this? GBATEK is the single most useful document a GBA hacker could have). The source register for DMA channel 3 is at 0x040000D4, so take a peek at the value there by using the following command: mw 040000d4 which gives: 040000d4 088d6760 06013000 04000000 00000000 `g...0.......... 040000e4 00000000 00000000 00000000 00000000 ................ 040000f4 00000000 00000000 00000000 0080fd44 ............D... ... So, the data has been copied from 088D6760. Note that the next word in memory is 06013000 - sounds familiar? It's the destination address (040000d8 is the destination register for channel 3). That concludes this brief tutorial - if all of that was greek to you, it'd probably pay to start with something a bit easier. Very Important Caveat: Although the steps up to setting the breakpoint will be the same for most games (though the graphics might be in one of the other Character bases in the tile viewer), the way the game gets that data into VRAM will differ. Some may use a Software Interrupt (SWI) to copy or decompress the data from a ROM address - others will have their own functions to decompress graphics (sometimes directly to VRAM, others into WRAM, then copied into VRAM using DMA or a SWI, or even with stmia/ldmia opcodes), so it's up to you to figure out what's going on past this point. I'll eventually get around to writing similar tutorials for other games, so that you can see how this might work.